/*******************************************************************************
 * The MOSES project, model based software engineering of networked embedded systems.
 * 
 * Copyright (C) 2010-2013, University of Applied Sciences Wildau,
 * Telematics Research Group, http://www.tm.th-wildau.de/research-group
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses>.
 * 
 * Contributors:
 *     University of Applied Sciences Wildau - initial API and implementation
 * 
 * If you are interested in a commercial license please contact us via 
 * e-mail: ralf.vandenhouten@th-wildau.de.
 ******************************************************************************/
package de.thwildau.tm.moses.common.builder;

import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;

/**
 * A handler class to execute external <code>java.lang.Process</code> instances. This class executes all
 * Processes in a separate Thread and will return after a given Timeout. This avoids possible Deadlock's of
 * the calling application that depend on the underlying external Processes.
 * 
 * @author Thomas Kistel
 * @version $Revision$
 */
public interface IProcessExecutor {

    /**
     * Enumeration from where the results of the <code>java.lang.Process</code> should be read. This could be
     * either the input or error stream of the subprocess. If <code>NONE</code> is specified, no results will
     * be read from the subprocess.
     */
    public enum ResultType {
        /** Do not read result from the subprocess. */
        NONE,
        /** Read the results from the input stream of the subprocess. */
        INPUT_STREAM,
        /** Read the results from the error stream of the subprocess. */
        ERROR_STREAM
    }

    /**
     * Result handlers are responsible for receiving the results from the underlying subprocess. The Result
     * handler receives the results in the form of String messages from the input or error stream of the
     * subprocess (see {@link ResultType}). If {@link ResultType#NONE} is used to execute the process no
     * result are received. In this case the {@link #onFinished(List)} method is called with an empty list to
     * indicate the completion of the subprocess.
     */
    public interface ResultHandler {

        /**
         * Is called once interim result is received from the subprocess.
         * 
         * @param resultLine the interim result from the subprocess
         */
        public void onProcess(String resultLine);
        
        /**
         * Is called once interim error result is received from the subprocess.
         * 
         * @param resultLine the interim error result from the subprocess
         */
        public void onError(String errorLine);

        /**
         * Is called when the subprocess is completely finished. All result that were read from the input or
         * error stream are passed to this method. The <code>resultLines</code> list contains the accumulated
         * result that were passed to {@link #onProcess(String)}.
         * <p>
         * If {@link ResultType#NONE} is used to execute the process, this method is called with an empty
         * list to indicate the completion of the subprocess.
         * </p>
         * 
         * @param resultLines the results of the subprocess
         */
        public void onFinished(List<String> resultLines);
        
        /**
         * Is called when the subprocess is completely finished. All result that were read from the 
         * error stream are passed to this method.
         * 
         * @param resultLines the error messages
         */
        public void onFinishedWithErrors(List<String> resultLines);


        /**
         * An empty implementation of the {@link ResultHandler} interface that does nothing.
         */
        class Stub implements ResultHandler {

            @Override
            public void onProcess(String resultLine) {
            }
            
            @Override
            public void onError(String errorLine) {
            }

            @Override
            public void onFinished(List<String> resultLines) {
            }

            @Override
            public void onFinishedWithErrors(List<String> resultLines) {
            }            
        }
    }


    /**
     * Executes the given Command. The <code>command</code> is passed to
     * {@link java.lang.Runtime#exec(String)}.
     * 
     * @param command the command string to execute the external process.
     * @param resultHandler the handler that process the results from the subprocess
     * @param resultTypes the kind of the result stream that should be used
     * @return the Status of the successful execution or failure of the subprocess
     */
    public abstract IStatus execCommand(String command, ResultHandler resultHandler, ResultType... resultTypes);

    /**
     * Executes the given Command. The <code>command</code> is passed to
     * {@link java.lang.Runtime#exec(String)}. This method uses a {@link IProgressMonitor} to report the
     * progress of the execution.
     * 
     * @param monitor the progress monitor
     * @param timeout the timeout in milliseconds to wait for the result. If the timeout exceeds this method
     *        returns with an Error-Status. In this case it is possible that further result are passed to the
     *        <code>resultHandler</code>.
     * @param command the command string to execute the external process.
     * @param resultHandler the handler that process the results from the subprocess
     * @param resultTypes the kind of the result stream that should be used
     * @return the Status of the successful execution or failure of the subprocess
     */
    public abstract IStatus execCommand(IProgressMonitor monitor, int timeout, String command,
            ResultHandler resultHandler, ResultType... resultTypes);

}
